﻿#if NETSTANDARD2_0 || NETCOREAPP3_0
using Microsoft.Extensions.Logging;
#endif
using System;

namespace Longbow.Logging
{
    /// <summary>
    /// 
    /// </summary>
    internal class Logger : ILogger
    {
        /// <summary>
        /// 
        /// </summary>
        protected Action<string> LogCallback { get; set; }

        /// <summary>
        /// 
        /// </summary>
        protected string Name { get; set; }

        /// <summary>
        /// 
        /// </summary>
        protected Func<string, LogLevel, bool> Filter { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="logCallback"></param>
        /// <param name="filter"></param>
        public Logger(string name, Action<string> logCallback, Func<string, LogLevel, bool> filter = null)
        {
            Name = name;
            LogCallback = logCallback;
            Filter = filter ?? ((category, logLevel) => true);
        }

        /// <summary>
        /// 判断当前 logLevel 是否开启日志
        /// </summary>
        /// <param name="logLevel">LogLevel 实例</param>
        /// <returns>开启日志时返回真</returns>
        public virtual bool IsEnabled(LogLevel logLevel) => logLevel == LogLevel.None ? false : Filter(Name, logLevel);

#if NETSTANDARD2_0 || NETCOREAPP3_0
        /// <summary>
        /// 获得/设置 IExternalScopeProvider 实例
        /// </summary>
        public IExternalScopeProvider ScopeProvider { get; set; }

        /// <summary>
        /// 开始创建日志上下文作用域
        /// </summary>
        /// <typeparam name="TState"></typeparam>
        /// <param name="state"></param>
        /// <returns></returns>
        public IDisposable BeginScope<TState>(TState state) => ScopeProvider?.Push(state) ?? NullScope.Instance;

        /// <summary>
        /// 写日志方法
        /// </summary>
        /// <typeparam name="TState">泛型类型</typeparam>
        /// <param name="logLevel">LogLevel 实例</param>
        /// <param name="eventId">eventId 实例</param>
        /// <param name="state">TState 实例</param>
        /// <param name="exception">Exception 实例</param>
        /// <param name="formatter">格式化方法回调函数</param>
        public virtual void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel)) return;

            var message = formatter.Invoke(state, exception);
            if (!string.IsNullOrEmpty(message) || exception != null)
            {
                LogCallback?.Invoke(message);
            }
        }
#else
        /// <summary>
        /// 
        /// </summary>
        /// <param name="logLevel"></param>
        /// <param name="message"></param>
        public virtual void Log(LogLevel logLevel, string message)
        {
            if (!IsEnabled(logLevel)) return;
            LogCallback?.Invoke(message);
        }
#endif
    }
}
